package service

import (
	"newRetailByGolang/model"
	"newRetailByGolang/pool"
	"newRetailByGolang/utils"
	"sync"
	"time"
)

type RetailService struct {
	ParticipationRecord *model.ParticipationRecord
	RegistrationActivitie *model.RegistrationActivitie
	User *model.User
	UpgradeRecord *model.UpgradeRecord
	Agent *model.Agent
	Store *model.Store
	TaskRecord *model.TaskRecord
	lock sync.Mutex
}

func NewRetailService() *RetailService {
	return &RetailService{
		ParticipationRecord:   new(model.ParticipationRecord),
		RegistrationActivitie: new(model.RegistrationActivitie),
		User:                  new(model.User),
		UpgradeRecord:         new(model.UpgradeRecord),
		Agent:                 new(model.Agent),
		Store:                 new(model.Store),
		TaskRecord:            new(model.TaskRecord),
		lock: sync.Mutex{},
	}
}

func (retailService *RetailService) UpgradeProcessing(activitie *model.RegistrationActivitie, participation *model.ParticipationRecord, userId int64, addNumber float32) {
	if activitie.LevelId == 5 {
		upgradeList := retailService.UpgradeRecord.FindUpgrade(activitie.StartTime, activitie.EndTime, 1, userId, participation.UserId, activitie.Id)
		if len(upgradeList) >= 1 {
			retailService.lock.Lock()
			retailService.ParticipationRecord.UpdateTasksNumber(activitie.Id, participation.UserId, participation.CompletedTasksNumber+addNumber)
			retailService.lock.Unlock()

			for _, upgrade := range upgradeList {
				w := new(utils.Worker)
				tr := model.TaskRecord{
					Id:                      w.GetId(),
					UserId:                  participation.UserId,
					RegistrationActivitieId: activitie.Id,
					UpgradeRecordId:         upgrade.Id,
					CreatedAt:               time.Now(),
					UpdatedAt:               time.Now(),
				}
				retailService.TaskRecord.InsertTaskRecord(&tr)
			}

			//for _, upgrade := range upgradeList {
			//	retailService.UpgradeRecord.UpdateUpgrade(upgrade.Id)
			//}

		}
	} else if activitie.LevelId == 6 {
		upgradeList := retailService.UpgradeRecord.FindUpgrade(activitie.StartTime, activitie.EndTime, 2, userId, participation.UserId, activitie.Id)
		if len(upgradeList) >= 1 {
			retailService.lock.Lock()
			retailService.ParticipationRecord.UpdateTasksNumber(activitie.Id, participation.UserId, participation.CompletedTasksNumber+addNumber)
			retailService.lock.Unlock()

			for _, upgrade := range upgradeList {
				w := new(utils.Worker)
				tr := model.TaskRecord{
					Id:                      w.GetId(),
					UserId:                  participation.UserId,
					RegistrationActivitieId: activitie.Id,
					UpgradeRecordId:         upgrade.Id,
					CreatedAt:               time.Now(),
					UpdatedAt:               time.Now(),
				}
				retailService.TaskRecord.InsertTaskRecord(&tr)
			}

			//for _, upgrade := range upgradeList {
			//	retailService.UpgradeRecord.UpdateUpgrade(upgrade.Id)
			//}
		}
	}
}

func (retailService *RetailService) InfiniteAgent(subAgentList *[]*model.Agent, activitie *model.RegistrationActivitie, participation *model.ParticipationRecord, addNumber float32) {
	if *subAgentList != nil {
		for _, subAgent := range *subAgentList {
			retailService.UpgradeProcessing(activitie, participation, subAgent.UserId, addNumber)

			store := retailService.Store.FindStoreByAgentId(subAgent.Id)
			user := retailService.User.FindUserById(store.UserId)
			if store.Id != 0 && user.VipLevel == 3{
				infiniteSubUserList := retailService.User.FindSubordinates(store.UserId)
				retailService.InfiniteSubordinate(&infiniteSubUserList, activitie, participation, addNumber/2)
			}else{
				infiniteSubAgentList := retailService.Agent.FindSubordinateAgent(subAgent.Id)
				if infiniteSubAgentList != nil {
					retailService.InfiniteAgent(&infiniteSubAgentList, activitie, participation, addNumber/2)
				}
			}
		}
	}
}

func (retailService *RetailService) InfiniteSubordinate(subUserList *[]*model.User, activitie *model.RegistrationActivitie, participation *model.ParticipationRecord, addNumber float32) {
	if *subUserList != nil {
		for _, subUser := range *subUserList {
			retailService.UpgradeProcessing(activitie, participation, subUser.Id, addNumber)

			infiniteSubUserList := retailService.User.FindSubordinates(subUser.Id)
			if infiniteSubUserList != nil {
				retailService.InfiniteSubordinate(&infiniteSubUserList, activitie, participation, addNumber/2)
			}
		}
	}
}

func (retailService *RetailService) StatisticalActivities(page int) func() error{
	return func() error {
		activitieList := retailService.RegistrationActivitie.QueryActivitieAll(page)
		for _, activitie := range activitieList {
			participationList := retailService.ParticipationRecord.QueryParticipationByActivitieId(activitie.Id)
			for _, participation := range participationList {
				subUserList := retailService.User.FindSubordinates(participation.UserId)
				user := retailService.User.FindUserById(participation.UserId)
				subAgentList := retailService.Agent.FindSubordinateAgentByUserId(user.Id)
				reallySubAgentList := retailService.Agent.FindSubordinateAgentBySupId(user.Id)
				if activitie.TypeId == 0 {
					if user.AgentLevel > 0 {
						for _, subAgent := range reallySubAgentList {
							retailService.UpgradeProcessing(activitie, participation, subAgent.UserId, 1.00)
						}
					} else {
						for _, subUser := range subUserList {
							retailService.UpgradeProcessing(activitie, participation, subUser.Id, 1.00)
						}
					}
				} else {
					var addNumber float32 = 1.00
					if user.AgentLevel > 0 {
						retailService.InfiniteAgent(&subAgentList, activitie, participation, addNumber)
					} else {
						retailService.InfiniteSubordinate(&subUserList, activitie, participation, addNumber)
					}
				}
			}
		}

		return nil
	}
}

func (retailService *RetailService) HandleTask() error {
	count := retailService.RegistrationActivitie.QueryActivitieAllTotal()
	page := int(count) / 10
	p := pool.NewSimplePoll(page + 1)
	for i := 0; i < page + 1; i++ {
		p.Add(retailService.StatisticalActivities(i))
	}
	p.Run()

	return nil
}